package com.pink.controller;

import com.pink.entity.config.AppConfig;
import com.pink.entity.config.Constants;
import com.pink.entity.dto.UserDto;
import com.pink.entity.enums.DateTimePatternEnum;
import com.pink.entity.enums.ResponseCodeEnum;
import com.pink.entity.vo.RestBeanVo;
import com.pink.entity.vo.response.SysSettingVo;
import com.pink.entity.vo.response.UploadingFileVo;
import com.pink.exception.BusinessException;
import com.pink.utils.DateUtil;
import com.pink.utils.FFmpegUtils;
import com.pink.utils.StringTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;

@RestController
@RequestMapping("/api/file")
@Validated
@Slf4j
public class fileController extends ABaseController{

    @Resource
    AppConfig appConfig;

    @Resource
    FFmpegUtils ffmpegUtils;

    /**
     * 上传用户头像
     * @param file
     * @param createThumbnail
     * @return
     * @throws IOException
     */
    @RequestMapping("/uploadUserImage")
    public RestBeanVo<String> uploadUserImage(@NotNull MultipartFile file, @NotNull Boolean createThumbnail) throws IOException {
        String month = DateUtil.format(new Date(), DateTimePatternEnum.YYYY_MM.getPattern());
        String folder = appConfig.getProjectFolder() + Constants.FILE_FOLDER + Constants.FILE_USER_IMAGE + month;
        File folderFile = new File(folder);
        if (!folderFile.exists()) {
            folderFile.mkdirs();
        }
        String fileName = file.getOriginalFilename();
        String fileSuffix = StringTool.getFileSuffix(fileName);
        String realFileName = StringTool.getRandomString(Constants.LENGTH_30) + fileSuffix;
        String filePath = folder + "/" + realFileName;
        file.transferTo(new File(filePath));
        if(createThumbnail){
            //生成缩略图
            ffmpegUtils.createImageThumbnail(filePath);
        }
        return RestBeanVo.success(Constants.FILE_USER_IMAGE + month + "/" + realFileName);
    }

    /**
     * 上传图片封面
     * @param file
     * @param createThumbnail
     * @return
     * @throws IOException
     */
    @RequestMapping("/uploadImage")
    public RestBeanVo<String> uploadImage(@NotNull MultipartFile file, @NotNull Boolean createThumbnail) throws IOException {
        String month = DateUtil.format(new Date(), DateTimePatternEnum.YYYY_MM.getPattern());
        String folder = appConfig.getProjectFolder() + Constants.FILE_FOLDER + Constants.FILE_COVER + month;
        File folderFile = new File(folder);
        if (!folderFile.exists()) {
            folderFile.mkdirs();
        }
        String fileName = file.getOriginalFilename();
        String fileSuffix = StringTool.getFileSuffix(fileName);
        String realFileName = StringTool.getRandomString(Constants.LENGTH_30) + fileSuffix;
        String filePath = folder + "/" + realFileName;
        file.transferTo(new File(filePath));
        if(createThumbnail){
            //生成缩略图
            ffmpegUtils.createImageThumbnail(filePath);
        }
        return RestBeanVo.success(Constants.FILE_COVER + month + "/" + realFileName);
    }

    /**
     * 预上传视频文件信息，返回上传id
     * @param fileName
     * @param chunks
     * @return
     */
    @RequestMapping("/preUploadVideo")
    public RestBeanVo<String> preUploadVideo(@NotNull String fileName, @NotNull String chunks){
        UserDto tokenUserDto = getTokenUserDto();
        if(tokenUserDto == null){
            throw new BusinessException("请先登录");
        }
        String uploadId = redisComponent.svaPreVideoFileInfo(String.valueOf(tokenUserDto.getUserId()),fileName,Integer.valueOf(chunks));
        return RestBeanVo.success(uploadId);
    }

    /**
     * 上传视频文件分片
     * @param chunkFile
     * @param uploadId
     * @param chunkIndex
     * @return
     * @throws IOException
     */
    @RequestMapping("/uploadVideo")
    public RestBeanVo<String> uploadVideo(@NotNull MultipartFile chunkFile, @NotNull String uploadId, @NotNull Integer chunkIndex) throws IOException {
        UserDto tokenUserDto = getTokenUserDto();
        if(tokenUserDto == null){
            throw new BusinessException("请先登录");
        }
        UploadingFileVo fileDto = redisComponent.UploadingFileVo(tokenUserDto.getUserId(),uploadId);
        if(fileDto == null){
            throw new BusinessException("上传信息不存在");
        }
        if(appConfig.getUpdataSize()){
            SysSettingVo sysSettingDto = redisComponent.getSysSettingVo();
            if(fileDto.getFileSize() > sysSettingDto.getVideoSize() * Constants.MB_SIZE){
                throw new BusinessException("文件大小超过限制");
            }
        }
        if((chunkIndex-1)>fileDto.getChunkIndex() || chunkIndex > fileDto.getChunks() - 1){
            throw new BusinessException(ResponseCodeEnum.CODE_600.getMessage());
        }
        String folder = appConfig.getProjectFolder()+Constants.FILE_FOLDER+Constants.FILE_FOllDER_TEMP + fileDto.getFilePath();
        File targetFile = new File(folder + "/" + chunkIndex);
        chunkFile.transferTo(targetFile);
        fileDto.setChunkIndex(chunkIndex);
        fileDto.setFileSize(fileDto.getFileSize() + chunkFile.getSize());
        redisComponent.updateVideoFileInfo(tokenUserDto.getUserId(),fileDto);
        return RestBeanVo.success("上传成功");
    }

    /**
     * 展示文件的接口
     * @param response
     * @param sourceName
     * @throws IOException
     */
    @RequestMapping("/getResource")
    public void getResource(HttpServletResponse response, @NotNull String sourceName) throws IOException {
        if(!StringTool.pathIsOK(sourceName)){
            throw new BusinessException(ResponseCodeEnum.CODE_600.getMessage());
        }
        String suffix = StringTool.getFileSuffix(sourceName);
        response.setContentType("image/"+suffix.replace(".",""));
        response.setHeader("Cache-Control","max-age=2592000");//设置缓存时间 30天
        readFile(response,sourceName);
    }

    //读取文件
    protected void readFile(HttpServletResponse response,String filePath){
        File file = new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER + filePath);
        log.info("文件路径:{}",file.getPath());
        if(!file.exists()){
            return;
        }
        try (OutputStream out = response.getOutputStream(); FileInputStream in = new FileInputStream(file)){
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
            out.flush();
        }catch (Exception e){
            log.error("文件读取失败",e);
        }
    }
}
